package org.tgcloud.group.service.manager;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.tgcloud.group.core.*;
import org.tgcloud.group.core.session.SessionFactory;
import org.tgcloud.group.entity.LogInfo;
import org.tgcloud.group.entity.SysManagerUser;
import org.tgcloud.group.entity.SysRole;
import org.tgcloud.group.repository.*;
import org.tgcloud.group.web.controller.dto.sys.SysButtonDTO;
import org.tgcloud.group.web.controller.dto.sys.SysMenuDTO;
import org.tgcloud.group.web.controller.dto.sys.SysRoleDTO;
import org.tgcloud.group.web.controller.dto.user.ManageUserDTO;

import java.util.*;
import java.util.stream.Collectors;

import static org.tgcloud.group.core.BaseLogger.printErrorInfo;

/**
 * @author: zhy
 * @create: 2023-07-17 13:29
 * @description:
 */
@Service
public class PermissionManagerService {


    @Autowired
    private SessionFactory sessionFactory;

    @Autowired
    private LogInfoMapper logInfoMapper;

    @Autowired
    private SysManagerUserMapper managerUserMapper;

    @Autowired
    private SysPermissionMapper sysPermissionMapper;

    @Autowired
    private RobotUserPermissionMapper userPermissionMapper;

    @Autowired
    private SysPermissionRoleMapper permissionRoleMapper;



    @Autowired
    private SysRoleMapper roleMapper;


    public APPResultMessage getUserPermissionList(int userId, String roleIds) {
        List<SysMenuDTO> mapList = new ArrayList<>();
        for (String roleId : roleIds.split(",")){
            List<SysMenuDTO> roleMapList = sysPermissionMapper.selectLoginListByUserId(userId, Integer.valueOf(roleId));
            mapList.addAll(roleMapList);
        }
        // 对mapList进行修改，把每个子list里的数据都变成一条
        List<SysMenuDTO> subList = new ArrayList<>();
        for (SysMenuDTO dto : mapList){
            SysMenuDTO sysMenuDTO = new SysMenuDTO();
            BeanUtils.copyProperties(dto, sysMenuDTO);
            boolean hasAdd = false;
            Integer addIndex = null;
            for (int i = 0;i < subList.size(); i++){
                SysMenuDTO subDto = subList.get(i);
                if (subDto.getId().equals(dto.getId()) && !hasAdd){
                    hasAdd = true;
                    if (BeanUtil.isNullList(subDto.getList())){
                        addIndex = i;
                    }
                }
            }
            if (!BeanUtil.isNullList(dto.getList())){
                for (SysButtonDTO buttonDTO : dto.getList()){
                    SysMenuDTO sysMenuDTO1 = new SysMenuDTO();
                    BeanUtils.copyProperties(dto, sysMenuDTO1);
                    List<SysButtonDTO> addList = new ArrayList<>();
                    addList.add(buttonDTO);
                    if (addIndex == null){
                        sysMenuDTO1.setList(addList);
                        subList.add(sysMenuDTO1);
                    }else if (addIndex != null && BeanUtil.isNullList(subList.get(addIndex).getList())){
                        subList.get(addIndex).setList(addList);
                    }
                }
            }else {
                if (!hasAdd){
                    sysMenuDTO.setList(null);
                    subList.add(sysMenuDTO);
                }
            }
        }
        // 对subList进行去重
        List<SysMenuDTO> collect = subList.stream().distinct().collect(Collectors.toList());
        List<SysMenuDTO> finalList = new ArrayList<>();
        for (SysMenuDTO dto : collect){
            if (!BeanUtil.isNullList(finalList)){
                if (finalList.stream().noneMatch(dto1 -> dto1.getId().equals(dto.getId()))){
                    finalList.add(dto);
                }else {
                    Integer finalIndex = null;
                    for (int i = 0; i < finalList.size(); i++){
                        if(finalList.get(i).getId().equals(dto.getId())){
                            finalIndex = i;
                        }
                    }
                    // id符合条件
                    if (dto.getList() != null){
                        // 判断按钮列表
                        for (SysButtonDTO buttonDTO : dto.getList()){
                            if (finalIndex != null && finalList.get(finalIndex).getList().stream().noneMatch(dto1 -> dto1.getButtonId().equals(buttonDTO.getButtonId()))){
                                List<SysButtonDTO> list = finalList.get(finalIndex).getList();
                                List<SysButtonDTO> addList = new ArrayList<>(list);
                                addList.add(buttonDTO);
                                finalList.get(finalIndex).setList(addList);
                            }
                        }
                    }else {
                        finalList.add(dto);
                    }
                }
            }else {
                finalList.add(dto);
            }
        }
        APPResultMessage successMessage = APPResultMessage.getSuccessMessage();
        ResultMessage resultMessage = ResultMessage.builder().setList(finalList);
        successMessage.setResult(resultMessage);
        return successMessage;
    }


    public APPResultMessage doUpPermission(int id, int userId, String ids, Short userType) {
        String key = "doUpUserPower_" + userId;
        String requestId = UUID.randomUUID().toString();
        boolean flag = LockUtil.tryGetDistributedLock(key, requestId);
        APPResultMessage message = APPResultMessage.getSuccessMessage();
        if (flag) {
            try {
                if(userType == null){
                    SysManagerUser managerUser = managerUserMapper.selectMsgByUserId(userId);
                    if (managerUser != null){
                        userId = managerUser.getId();
                    }
                }
                List<Integer> powerIds = (List<Integer>) JSON.parse(ids);
//                Integer[] powerIds = (Integer[]) JSON.parse(ids);
                List<Integer> is = userPermissionMapper.selectPowerIdListByUserId(userId);
                ArrayList<Integer> tmps = Lists.newArrayList(powerIds); // 中间集合
                // 移除已存在的
//                List<Integer> pids = Arrays.asList(powerIds); // 无法使用add和remove方法
                List<Integer> pids = powerIds;
                ArrayList<Integer> integers = Lists.newArrayList(pids); // 再做一次处理
                integers.removeAll(is); // 新增
                is.removeAll(tmps); // 移除
                // 批量插入
                if (!BeanUtil.isNullList(integers)) {
                    // 获取已被删除的权限
                    List<Integer> isDel = userPermissionMapper.selectPowerIdsByIds(userId);
                    // 存在已被删除的直接修改状态变为可用
                    // isDel获取交集
                    isDel.retainAll(integers);
                    if (!BeanUtil.isNullList(isDel)) {
                        userPermissionMapper.updateBatchById(userId, isDel, (short) 1);
                    }
                    // 移除交集，余下的新增
                    integers.removeAll(isDel);
                    if (!BeanUtil.isNullList(integers)) {
                        userPermissionMapper.insetBatch(userId, integers, new Date());
                    }
                }
                // 批量删除
                if (!BeanUtil.isNullList(is)) {
                    userPermissionMapper.updateBatchById(userId, is, (short) 2);
                }
                if (BeanUtil.isNullList(is)) {
                    SysManagerUser user = managerUserMapper.selectByPrimaryKey(userId);
                    String[] split = user.getRoleId().split(",");
                    List<Integer> sysRoles = new ArrayList<>();
                    for (String roleId : split){
                        List<Integer> sysSubRoles = permissionRoleMapper.selectPowerIdByUserType(Integer.valueOf(roleId)); //查询角色权限
                        sysRoles.addAll(sysSubRoles);
                    }
                    List<Integer> collect = sysRoles.stream().distinct().collect(Collectors.toList());
                    ArrayList<Integer> s = Lists.newArrayList(collect);
                    ArrayList<Integer> roles = Lists.newArrayList(pids); // 再重新获取做一次处理
                    s.removeAll(roles); // 移除
                    if (!BeanUtil.isNullList(s)) {
                        userPermissionMapper.insetBatchByStatus(userId, s, (short) 2, new Date());
                    }
                }
                destroyToken(userId, null);
            } catch (Exception e) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                printErrorInfo(e);
                message = APPResultMessage.SYSTEM_ERROR();
            } finally {
                LockUtil.releaseDistributedLock(key, requestId);
                return message;
            }
        } else {
            return APPResultMessage.SYSTEM_BUSY();
        }
    }

    @Async
    public void destroyToken(Integer userId, Integer roleId) {
        if (userId != null) {
            LogInfo logInfo = logInfoMapper.selectByUserId(userId);
            if (logInfo != null) {
                sessionFactory.destroySession(logInfo.getToken());
            }
        }
        if (roleId != null) {
            List<LogInfo> logInfos = logInfoMapper.selectListByRoleId(roleId);
            if (!BeanUtil.isNullList(logInfos)) {
                for (LogInfo info : logInfos) {
                    sessionFactory.destroySession(info.getToken());
                }
            }
        }
    }


    public APPResultMessage getEditUserRoleList() {
        List<SysRole> sysRoles = roleMapper.selectEditUserRoleList();
        APPResultMessage message = APPResultMessage.getSuccessMessage();
        ResultMessage builder = ResultMessage.builder();
        builder.setList(sysRoles);
        message.setResult(builder);
        return message;
    }

    public APPResultMessage getPermissionList(int id, Integer userId, Short userType) {
        if (userId == null) {
            userId = id;
        }
        if (userType != null && userType == 1){
            SysManagerUser managerUser = managerUserMapper.selectMsgByUserId(userId);
            userId = managerUser.getId();
        }
        List<SysMenuDTO> mapList = sysPermissionMapper.selectListByUserId(userId,userType);
        ResultMessage resultMessage = ResultMessage.builder().setList(mapList);
        APPResultMessage successMessage = APPResultMessage.getSuccessMessage();
        successMessage.setResult(resultMessage);
        return successMessage;
    }


    public APPResultMessage getRoleList(String keyword, Integer pageNum, Integer pageSize, Long startTime, Long endTime, Short sort) {
        Date start = startTime == null ? null : new Date(startTime);
        Date end = endTime == null ? null : new Date(endTime);
        if (pageNum != null && pageSize != null) {
            PageHelper.startPage(pageNum, pageSize);
            List<SysRoleDTO> sysRoles = roleMapper.selectListByKeyword(keyword, start, end, sort);
            PageInfo<SysRoleDTO> tables = new PageInfo<>(sysRoles);

            // 获取用户数量
            if (!BeanUtil.isNullList(tables.getList())) {
                for (SysRoleDTO sysRole : tables.getList()) {
                    Integer roleId = sysRole.getId();

                    String roleUserNumHeader = GlobalStatic.role_user_num + roleId;
                    Long roleUserNum = RedisUtil.getSetCacheIncrementLong(roleUserNumHeader, 0l);
                    if (roleUserNum.longValue() == 0l) {
                        int i = managerUserMapper.countByRoleId(roleId);
                        RedisUtil.setCacheIncrement(roleUserNumHeader, i);
                    }
                    sysRole.setUserNum(RedisUtil.getCacheLong(roleUserNumHeader));
                }
            }

            ResultMessage result = ResultMessage.builder().setList(tables.getList()).setAllPageNumber(tables.getPages()).setCount(tables.getTotal());
            APPResultMessage message = APPResultMessage.getSuccessMessage();
            message.setResult(result);
            return message;
        } else {
            List<SysRoleDTO> sysRoles = roleMapper.selectListByKeyword(keyword, start, end, sort);

            // 获取用户数量
            if (!BeanUtil.isNullList(sysRoles)) {
                for (SysRoleDTO sysRole : sysRoles) {
                    Integer roleId = sysRole.getId();
                    String roleUserNumHeader = GlobalStatic.role_user_num + roleId;
                    Long roleUserNum = RedisUtil.getSetCacheIncrementLong(roleUserNumHeader, 0l);
                    if (roleUserNum.longValue() == 0l) {
                        int i = managerUserMapper.countByRoleId(roleId);
                        RedisUtil.setCacheIncrement(roleUserNumHeader, i);
                    } else {
                        sysRole.setUserNum(RedisUtil.getCacheLong(roleUserNumHeader));
                    }
                }
            }

            APPResultMessage successMessage = APPResultMessage.getSuccessMessage();
            ResultMessage resultMessage = ResultMessage.builder().setList(sysRoles);
            successMessage.setResult(resultMessage);
            return successMessage;
        }
    }


    public APPResultMessage doAddUpRole(String roleName, Integer roleId, Short viewAll, String customName, Short multipleType) {
        String key = "doUpRole_id_name_" + roleName;
        String requestId = UUID.randomUUID().toString();
        boolean flag = LockUtil.tryGetDistributedLock(key, requestId);
        if (flag) {
            if (roleId == null) {
                SysRole sysRole = roleMapper.selectMsgByRoleName(roleName);
                if (sysRole != null) {
                    LockUtil.releaseDistributedLock(key, requestId);
                    return APPResultMessage.getErrorMessage("角色名已存在");
                }
                SysRole role = new SysRole();
                role.setRoleName(roleName);
                role.setCreateTime(new Date());
                role.setStatus((short) 1);
                role.setViewAll(viewAll);
                role.setCustomName(customName);
                role.setMultipleType(multipleType);
                roleMapper.insertSelective(role);
            } else {
                SysRole sysRole = roleMapper.selectMsgByNameAndId(roleName, roleId);
                if (sysRole != null) {
                    LockUtil.releaseDistributedLock(key, requestId);
                    return APPResultMessage.getErrorMessage("角色名已存在");
                }
                roleMapper.updateName(roleId, roleName, viewAll, customName, multipleType);
            }
            LockUtil.releaseDistributedLock(key, requestId);
            return APPResultMessage.getSuccessMessage();
        } else {
            return APPResultMessage.SYSTEM_BUSY();
        }
    }

    public APPResultMessage doDelRole(String ids) {
        String key = "doDelRole";
        String requestId = UUID.randomUUID().toString();
        boolean flag = LockUtil.tryGetDistributedLock(key, requestId);
        if (flag) {
            String[] split = ids.split(",");
            boolean hasNoDel = false; // 判断是否有不能删除的角色
            for (String sid : split){
                if(Integer.valueOf(sid) == 50){
                    hasNoDel = true;
                }
            }
            if (hasNoDel){
                return new APPResultMessage(6001, "有角色不能删除，请慎重选择");
            }
            int num = managerUserMapper.selectNeedDelNumByIds(split);
            if (num > 0) {
                LockUtil.releaseDistributedLock(key, requestId);
                return APPResultMessage.getErrorMessage("有" + num + "个用户未删除");
            }
            roleMapper.updateStatusByIds(split);
            for (String id : split) {
                // 删除角色用户数
                RedisUtil.deleteObject(GlobalStatic.role_user_num + id);
            }
            LockUtil.releaseDistributedLock(key, requestId);
            return APPResultMessage.getSuccessMessage();
        } else {
            return APPResultMessage.SYSTEM_BUSY();
        }
    }


    public APPResultMessage doDisenableRole(Integer id, Short type) {
        if (type.intValue() == 1) {
            roleMapper.updateStatusById(id, (short) 1);
        } else {
            roleMapper.updateStatusById(id, (short) 3);
        }
        return APPResultMessage.getSuccessMessage();
    }


    public APPResultMessage getRolePermissionList(int userId, int roleId) {
        List<SysMenuDTO> sysMenuDTOS = sysPermissionMapper.selectListByRoleId(roleId);
        APPResultMessage successMessage = APPResultMessage.getSuccessMessage();
        ResultMessage resultMessage = ResultMessage.builder().setList(sysMenuDTOS);
        successMessage.setResult(resultMessage);
        return successMessage;
    }


    public APPResultMessage doUpRolePermission(int roleId, String ids) {
        String key = "doUpRolePower_" + roleId;
        String requestId = UUID.randomUUID().toString();
        boolean flag = LockUtil.tryGetDistributedLock(key, requestId);
        APPResultMessage message = APPResultMessage.getSuccessMessage();
        if (flag) {
            try {
                List<Integer> powerIds = new ArrayList<Integer>();
                if(ids.indexOf("[") > 0){
                    powerIds = (List<Integer>) JSON.parse(ids);
                }else {
                    String[] split = ids.split(",");
                    for (String stringId : split){
                        powerIds.add(Integer.valueOf(stringId));
                    }
                }
                List<Integer> is = permissionRoleMapper.selectPowerIdListByUserId(roleId);
                ArrayList<Integer> tmps = Lists.newArrayList(powerIds); // 中间集合
                List<Integer> pids = powerIds;
                ArrayList<Integer> integers = Lists.newArrayList(pids); // 再做一次处理
                integers.removeAll(is); // 新增
                is.removeAll(tmps); // 移除
                // 批量插入
                if (!BeanUtil.isNullList(integers)) {
                    // 获取已被删除的权限
                    List<Integer> isDel = permissionRoleMapper.selectPowerIdsByIds(roleId);
                    // 存在已被删除的直接修改状态变为可用
                    // isDel获取交集
                    isDel.retainAll(integers);
                    if (!BeanUtil.isNullList(isDel)) {
                        permissionRoleMapper.updateBatchById(roleId, isDel, (short) 1);
                    }
                    // 移除交集，余下的新增
                    integers.removeAll(isDel);
                    if (!BeanUtil.isNullList(integers)) {
                        integers.add(1);
                        permissionRoleMapper.insetBatch(roleId, integers, new Date());
                    }
                }
                // 批量删除
                if (!BeanUtil.isNullList(is)) {
                    permissionRoleMapper.updateBatchById(roleId, is, (short) 2);
                }
                destroyToken(null, roleId);
            } catch (Exception e) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                printErrorInfo(e);
                message = APPResultMessage.SYSTEM_BUSY();
            } finally {
                LockUtil.releaseDistributedLock(key, requestId);
                return message;
            }
        } else {
            return APPResultMessage.SYSTEM_BUSY();
        }
    }


    public APPResultMessage getAllRoleList() {
        List<SysRoleDTO> sysRoles = roleMapper.selectListByKeyword(null, null, null, null);
        APPResultMessage successMessage = APPResultMessage.getSuccessMessage();
        ResultMessage resultMessage = ResultMessage.builder().setList(sysRoles);
        successMessage.setResult(resultMessage);
        return successMessage;
    }

    public APPResultMessage getAllCustomRoleList() {
        List<SysRole> list = roleMapper.selectCustomList();
        APPResultMessage successMessage = APPResultMessage.getSuccessMessage();
        ResultMessage resultMessage = ResultMessage.builder().setList(list);
        successMessage.setResult(resultMessage);
        return successMessage;
    }

    public APPResultMessage getAccountListByRoleIds(String roleIds) {
        JSONObject data = new JSONObject();
        String redisRoleKey = "roleUser:";
        String[] split = roleIds.split(",");
        for (String s : split){
            String redisKey = redisRoleKey + s;
            if(RedisUtil.existKey(redisKey)){
                List<ManageUserDTO> cacheList = RedisUtil.getCacheList(redisKey);
                data.put(s, cacheList);
            }else {
                List<ManageUserDTO> manageUserDTOS = managerUserMapper.selectListByRoleId(Integer.valueOf(s));
                RedisUtil.setCacheList(redisKey, manageUserDTOS);
                data.put(s, manageUserDTOS);
            }
        }
        APPResultMessage message = APPResultMessage.getSuccessMessage();
        ResultMessage resultMessage = ResultMessage.builder().setData(data);
        message.setResult(resultMessage);
        return message;
    }


    public void doUpdateRedisRoleUser(String roleIds){
        // 跟新redis中的角色用户数据，保证redis里的角色用户是最新的
        String redisRoleKey = "roleUser:";
        String[] split = roleIds.split(",");
        for (String s : split){
            String redisKey = redisRoleKey + s;
            List<ManageUserDTO> manageUserDTOS = managerUserMapper.selectListByRoleId(Integer.valueOf(s));
            RedisUtil.setCacheList(redisKey, manageUserDTOS);
        }
    }

}
